package ml.exp;

import android.graphics.SurfaceTexture;
import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.util.Log;

import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class MediaGLView {
    int texid_oes = 0;//oes tex对象
    SurfaceTexture _texsurface;
    int texid_fbo = 0;//fbo tex对象
    int fboid = 0;//fbo tex对象
    int fbo_width;
    int fbo_height;

    ByteBuffer pixelBufferRender;
    ByteBuffer pixelBufferRead;

    public MediaGLView(int width, int height) {
        this.fbo_width = width;
        this.fbo_height = height;
    }

    public ByteBuffer GetBuffer() {
        synchronized (this) {
            return pixelBufferRead;
        }
    }

    public boolean HasGLInit() {
        return this.texid_oes != 0;
    }

    public int GetTexID_OES() {
        return this.texid_oes;
    }
    public SurfaceTexture InitSurfaceTexture(int width,int height) {
        _texsurface = new SurfaceTexture(this.texid_oes);
        _texsurface.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
            boolean inited = false;

            @Override
            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
//                long threadid = Thread.currentThread().getId();
//                Log.w("==E==", "onFrameAvailable thread=" + threadid);
                //这里只是给出信号Texture 可用了
                if (!inited) {

                    _texsurface.setDefaultBufferSize(width, height);
                    inited = true;
                }
                _texdone = true;

            }
        });
        return this._texsurface;
    }
    boolean _texdone=false;
    public boolean IsTexDone() {
        return _texdone;
    }

    public void UpdateTexImage() {
        if (_texdone == true && this._texsurface != null) {
            this._texsurface.updateTexImage();
            _texdone = false;
        }
    }
    public int GetTexID_FBO() {
        return this.texid_fbo;
    }

    public int GetOutputWidth() {
        return this.fbo_width;
    }

    public int GetOutputHeight() {
        return this.fbo_height;
    }

    public void SetOutputSize(int width, int height) {
        this.fbo_width = width;
        this.fbo_height = height;
    }

    public void GL_Init() {
        Log.w("==E==","MediaGLView GL_Init");
        {//Init OES
            int[] texs = new int[1];

            GLES20.glGenTextures(1, texs, 0);
            this.texid_oes = texs[0];
            //GLES20.glTexImage2D();

            GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
            //GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texid);
            GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid_oes);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);


        }

        {//Init FBO
            int[] texs = new int[1];
            int[] bufs = new int[1];
            GLES20.glGenTextures(1, texs, 0);
            this.texid_fbo = texs[0];


            GLES20.glGenFramebuffers(1, bufs, 0);
            this.fboid = bufs[0];


            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, this.texid_fbo);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, fbo_width, fbo_height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
            GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboid);
            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texid_fbo, 0);
            GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
        }
        pixelBufferRender = ByteBuffer.allocateDirect(fbo_width * fbo_height * 4);
        pixelBufferRender.order(ByteOrder.nativeOrder());
        pixelBufferRead = ByteBuffer.allocateDirect(fbo_width * fbo_height * 4);
        pixelBufferRead.order(ByteOrder.nativeOrder());
    }

    public void GL_Release() {
        if (!HasGLInit())
            return;
        Log.w("==E==","MediaGLView GL_Release");
        GLES20.glDeleteFramebuffers(1, new int[]{this.fboid}, 0);
        _texsurface.releaseTexImage();
        _texsurface.release();
        _texsurface = null;
        GLES20.glDeleteTextures(2, new int[]{this.texid_oes, this.texid_fbo}, 0);

        pixelBufferRead = null;
        pixelBufferRender = null;
    }

    public void GL_Render2FBO(int ShaderProgOES) {
        if (!HasGLInit())
            return;
        ;
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fboid);

        GLES20.glViewport(0, 0, fbo_width, fbo_height);
        GLES20.glClearColor(0f, 0f, 1.0f, 1.0f);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);


        GLES20.glUseProgram(ShaderProgOES);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, texid_oes);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
        GLES20.glFlush();

    }

    void GL_EndRender() {
        if (!HasGLInit())
            return;
        ;
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    }

    void GL_Render2Pixel(int ShaderProgOES) {
        if (!HasGLInit())
            return;
        ;

        GL_Render2FBO(ShaderProgOES);

        {//read pixel
            pixelBufferRender.position(0);
            GLES20.glReadPixels(0, 0, fbo_width, fbo_height,
                    GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pixelBufferRender);
        }
        //交换缓存
        synchronized (this) {
            ByteBuffer A = pixelBufferRead;
            ByteBuffer B = pixelBufferRender;
            pixelBufferRender = A;
            pixelBufferRead = B;
        }
        GL_EndRender();
    }


}
